package com.geek.water.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geek.water.entity.Device;
import com.geek.water.entity.DeviceData;
import com.geek.water.entity.WorkOrder;
import com.geek.water.exception.WaterException;
import com.geek.water.mapper.DeviceDataMapper;
import com.geek.water.mapper.DeviceMapper;
import com.geek.water.mapper.WorkOrderMapper;
import com.geek.water.service.DeviceService;
import com.geek.water.vo.DevicePageQueryVO;
import com.geek.water.vo.PageQueryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author yangwenqi
 * @decs TODO
 * @date 2025/7/25
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {

    @Autowired
    private  DeviceDataMapper deviceDataMapper;
    @Autowired
    private  WorkOrderMapper workOrderMapper;

    @Override
    public Page<Device> findPage(DevicePageQueryVO queryVO) {
        if (queryVO == null) {
            queryVO = new DevicePageQueryVO();
        }

        int safePageSize = Math.min(queryVO.getPageSize() != null ? queryVO.getPageSize() : 10, 100);
        Page<Device> page = Page.of(
                queryVO.getCurrentPage() != null ? queryVO.getCurrentPage() : 1,
                safePageSize
        );

        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();

        // 修复1：添加空值检查的like条件
        if (StringUtils.hasText(queryVO.getQueryString())) {
            DevicePageQueryVO finalQueryVO = queryVO;
            wrapper.and(w -> w
                    .like(StringUtils.hasText(finalQueryVO.getQueryString()), Device::getModel, finalQueryVO.getQueryString())
                    .or()
                    .like(StringUtils.hasText(finalQueryVO.getQueryString()), Device::getSerialNo, finalQueryVO.getQueryString())
            );
        }

        Optional.ofNullable(queryVO.getStatus()).ifPresent(s -> wrapper.eq(Device::getStatus, s));
        Optional.ofNullable(queryVO.getAreaId()).ifPresent(id -> wrapper.eq(Device::getAreaId, id));

        // 注意：Device实体中没有billingPeriod字段，计费周期过滤逻辑需要根据业务需求调整
        // 如果需要按计费周期过滤，可能需要通过DeviceData表进行关联查询

        if (queryVO.getLastHeartbeatStart() != null && queryVO.getLastHeartbeatEnd() != null) {
            wrapper.between(Device::getLastHeartbeat,
                    queryVO.getLastHeartbeatStart(),
                    queryVO.getLastHeartbeatEnd());
        }

        // 修复2：使用安全字段映射的动态排序
        if (StringUtils.hasText(queryVO.getSortField())) {
            boolean isAsc = "asc".equalsIgnoreCase(queryVO.getSortOrder());
            SFunction<Device, ?> sortField = SORT_FIELD_MAPPING.getOrDefault(
                    queryVO.getSortField().trim(),
                    Device::getLastHeartbeat  // 默认排序字段
            );
            wrapper.orderBy(true, isAsc, sortField);
        } else {
            wrapper.orderByDesc(Device::getLastHeartbeat);
        }

        return baseMapper.selectPage(page, wrapper);
    }

    private static final Map<String, SFunction<Device, ?>> SORT_FIELD_MAPPING = new HashMap<>();
    static {
        SORT_FIELD_MAPPING.put("model", Device::getModel);
        SORT_FIELD_MAPPING.put("serialNo", Device::getSerialNo);
        SORT_FIELD_MAPPING.put("status", Device::getStatus);
        SORT_FIELD_MAPPING.put("lastHeartbeat", Device::getLastHeartbeat);
        SORT_FIELD_MAPPING.put("createdAt", Device::getCreatedAt);
        SORT_FIELD_MAPPING.put("currentReading", Device::getCurrentReading);
        SORT_FIELD_MAPPING.put("areaId", Device::getAreaId);
    }
    @Transactional
    @Override
    public boolean deleteById(Long id) {
        // 1. 检查设备是否有关联工单
        Long count = workOrderMapper.selectCount(
                new LambdaQueryWrapper<WorkOrder>().eq(WorkOrder::getDeviceId, id)
        );

        if (count > 0) {
            throw new WaterException("设备存在关联工单，无法删除");
        }

        // 2. 删除设备
        return baseMapper.deleteById(id) > 0;
    }

    @Override
    public List<DeviceData> getDeviceData(Long deviceId, LocalDateTime startTime, LocalDateTime endTime) {
        // 将LocalDateTime转换为LocalDate，因为DeviceData使用readingDate字段
        LocalDate startDate = startTime.toLocalDate();
        LocalDate endDate = endTime.toLocalDate();

        return deviceDataMapper.selectList(
                new LambdaQueryWrapper<DeviceData>()
                        .eq(DeviceData::getDeviceId, deviceId)
                        .between(DeviceData::getReadingDate, startDate, endDate)
                        .orderByAsc(DeviceData::getReadingDate)
        );
    }

    @Override
    public boolean uploadDeviceData(DeviceData deviceData) {
        return deviceDataMapper.insert(deviceData) > 0;
    }

    @Override
    public boolean isSerialNoUnique(String serialNo, Long excludeId) {
        if (serialNo == null || serialNo.trim().isEmpty()) {
            return false;
        }

        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getSerialNo, serialNo.trim());

        // 如果是更新操作，排除当前设备ID
        if (excludeId != null) {
            wrapper.ne(Device::getId, excludeId);
        }

        return baseMapper.selectCount(wrapper) == 0;
    }
}
